﻿using Sipek.Common;
using Sipek.Common.CallControl;
using Sipek.Sip;
using System.Linq;

namespace SoftPhone
{
    public class SIPManager
    {
        public static CCallManager CallManager
        {
            get { return CCallManager.Instance; }
        }

        private static PhoneConfig _config = new PhoneConfig();

        public static IStateMachine outcall = null;
        public static IStateMachine incall = null;        

        public delegate void IncomingCallHandle(string number);
        public static IncomingCallHandle IncomingCallNotification;
        public delegate void OnAccountChanged(string UserName);
        public static OnAccountChanged OnAccountChangedNotification;
        public delegate void CallStateChanged(int sessionid);
        public static CallStateChanged CallStateNotification;

        internal PhoneConfig Config
        {
            get { return _config; }
        }

        #region PhoneInitialLaunch
        public void InitalLogin(ref string message)
        {            
            var account = PolicyConfigClient.ReadConfig("Account");
            if (account != null)
            {
                MyAccount acc = new MyAccount()
                {
                    UserName = account.Where(a => a.Key == "UserName").SingleOrDefault().Value,
                    Id = account.Where(a => a.Key == "ID").SingleOrDefault().Value,
                    Password = account.Where(a => a.Key == "Password").SingleOrDefault().Value,
                    HostName = account.Where(a => a.Key == "Domain").SingleOrDefault().Value + ":" + account.Where(a => a.Key == "Port").SingleOrDefault().Value,
                    DomainName = "*",
                };
                if (!Register(acc))
                {
                    message = "Có vấn đề xảy ra khi đăng nhập tài khoản SIP." + "\n" + "Hãy kiểm tra tùy chỉnh thiết lập tài khoản và đăng nhập lại.";
                }
            }
        }

        public bool Register(MyAccount account)
        {
            try
            {
                MyAccount acc = new MyAccount()
                {
                    AccountName = account.AccountName,
                    UserName = account.UserName,
                    DomainName = account.DomainName,
                    HostName = account.HostName,
                    Id = account.Id,
                    Password = account.Password,
                };
                LaunchSIPPhone();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public void LaunchSIPPhone()
        {
            CallManager.StackProxy = pjsipStackProxy.Instance;
            CallManager.Config = Config;
            CallManager.IncomingCallNotification += CallManager_IncomingCallNotification;
            CallManager.CallStateRefresh += CallManager_CallStateRefresh;
            pjsipStackProxy.Instance.Config = Config;
            pjsipRegistrar.Instance.Config = Config;
            CallManager.Initialize();
            pjsipRegistrar.Instance.registerAccounts();            
            pjsipStackProxy.Instance.setCodecPriority("G722/16000/1", 0);

            if (OnAccountChangedNotification != null)
            {
                OnAccountChangedNotification(CallManager.Config.Accounts[0].UserName);
            }
        }

        #endregion

        #region CallNotification
        private void CallManager_CallStateRefresh(int sessionId)
        {
            if (CallStateNotification != null)
            {
                CallStateNotification(sessionId);
            }
        }

        private void CallManager_IncomingCallNotification(int sessionId, string number, string info)
        {
            if (IncomingCallNotification != null)
            {
                incall = CallManager.getCall(sessionId);
                IncomingCallNotification(number);
            }            
        }
        #endregion

        #region CallOperation
        public void CreateOutBoundCall(string number , ref string message)
        {
            try
            {
                outcall = CallManager.createOutboundCall(number);
            }
            catch
            {
                message = "Có lỗi xảy ra khi thực hiện tác vụ này";
                
            }
        }

        public void ReleaseCall(string number)
        {
            if (outcall != null)
            {
                if (number == outcall.CallingNumber)
                {
                    CallManager.onUserRelease(outcall.Session);
                    return;
                }
            }
            if (incall != null)
            {
                if (number == incall.CallingNumber)
                {
                    CallManager.onUserRelease(incall.Session);
                    return;
                }
            }
        }

        public void TransferCall(string number)
        {
            try
            {
                if (outcall != null)
                {
                    CallManager.onUserTransfer(outcall.Session, number);
                    return;
                }
                if (incall != null)
                {
                    CallManager.onUserTransfer(incall.Session, number);
                    return;
                }
            }
            catch
            {
                throw;
            }
        }

        public void HoldorRetrieveCall()
        {
            if (outcall != null)
            {
                CallManager.onUserHoldRetrieve(outcall.Session);
                return;
            }
            if (incall != null)
            {
                CallManager.onUserHoldRetrieve(incall.Session);
                return;
            }
        }

        public void AnswerCall(string number)
        {            
            if (outcall != null)
            {
                if (outcall.CallingNumber == number)
                {
                    CallManager.onUserAnswer(outcall.Session);
                    return;
                }
            }
            if (incall != null)
            {
                if (incall.CallingNumber == number)
                {
                    CallManager.onUserAnswer(incall.Session);
                    return;
                }
            }
        }
        #endregion

    }
}
